﻿#ifndef __SS_MYSQL_PARAM_H__
#define __SS_MYSQL_PARAM_H__

#ifdef _WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <memory.h>
#endif
#include "mysql.h"
#include "container/ssBuffer.h"
#include "time/ssTime.h"

#define DB_PARAM_FLAG_NUM		32
#define DB_BUFFER_LEN			102400	//字段最大长度100kb
#define DB_QUERY_NOT_EXIST		-9		//查询不存在
#define DB_PREPARE_ERROR		-8		//准备出错
#define DB_QUERY_CONNECT_NULL	-7		//连接不存在
#define DB_QUERY_NULL			-6		//没有数据
#define DB_QUERY_RESULE_ERROR	-5		//获取查询结果错误
#define DB_QUERY_LOGIC_ERROR	-4		//逻辑错误
#define DB_QUERY_PARAM_ERROR	-3		//参数错误
#define DB_QUERY_NAME_EXISTS	-2		//名字已存在
#define DB_QUERY_ERROR			-1		//查询出错
#define DB_QUERY_OK				0		//没有数据

#define DB_RESULT_INSERT_ID		1		//返回插入的新ID
#define DB_RESULT_NULL			2		//不返回记录集
#define DB_RESULT_ONE			4		//返回1条记录集
#define DB_RESULT_MULTI			8		//返回多条记录集
#define DB_RESULT_CLEAR			16		//清除缓存

namespace StarSeeker
{

class QueryParam_s
{
public:
	QueryParam_s():len(0), isNull(1), type(0) {}
	virtual ~QueryParam_s() {}
	//与mysql参数结构体绑定
	virtual void Bind(MYSQL_BIND &bd, unsigned int nLen)=0;
	//重置数据
	virtual void Reset()=0;
	//返回数据地址
	virtual const void* GetValueMemory()=0;
	//设置参数
	virtual bool SetValue(void* pData, unsigned int nLen)=0;

	unsigned long	len;	//数据长度
	my_bool			isNull;	//是否空值
	char			type;	//字段类型
};
//参数结构定义
//i4
class QueryInt_s : public QueryParam_s
{
public:
	QueryInt_s()
	{
		type = '1';
	}
	void Bind(MYSQL_BIND &bd, unsigned int nLen)
	{
		bd.buffer_type = MYSQL_TYPE_LONG;
		bd.buffer = &val;
		bd.length = &len;
		bd.buffer_length = sizeof(int);
		bd.is_null = &isNull;
		bd.is_unsigned = 0;
	}
	void Reset()
	{
		val = 0;
	}
	const void* GetValueMemory()
	{
		return &val;
	}
	bool SetValue(void* pData, unsigned int nLen)
	{
		if (pData)
		{
			val = *(int*)pData;
			isNull = 0;
		} 
		else
		{
			isNull = 1;
		}
		return true;
	}
private:
	int	val;
};
//u4
class QueryUInt_s : public QueryParam_s
{
public:
	QueryUInt_s()
	{
		type = '2';
	}
	void Bind(MYSQL_BIND &bd, unsigned int nLen)
	{
		bd.buffer_type = MYSQL_TYPE_LONG;
		bd.buffer = &val;
		bd.length = &len;
		bd.buffer_length = sizeof(unsigned int);
		bd.is_null = &isNull;
		bd.is_unsigned = 1;
	}
	void Reset()
	{
		val = 0;
	}
	const void* GetValueMemory()
	{
		return &val;
	}
	bool SetValue(void* pData, unsigned int nLen)
	{
		if (pData)
		{
			val = *(unsigned int*)pData;
			isNull = 0;
		}
		else
		{
			isNull = 1;
		}
		return true;
	}
private:
	unsigned int val;
};
//i1
class QueryChar_s : public QueryParam_s
{
public:
	QueryChar_s()
	{
		type = '3';
	}
	void Bind(MYSQL_BIND &bd, unsigned int nLen)
	{
		bd.buffer_type = MYSQL_TYPE_TINY;
		bd.buffer = &val;
		bd.length = &len;
		bd.buffer_length = sizeof(char);
		bd.is_null = &isNull;
		bd.is_unsigned = 0;
	}
	void Reset()
	{
		val = 0;
	}
	const void* GetValueMemory()
	{
		return &val;
	}
	bool SetValue(void* pData, unsigned int nLen)
	{
		if (pData)
		{
			val = *(char*)pData;
			isNull = 0;
		}
		else
		{
			isNull = 1;
		}
		return true;
	}
private:
	char val;
};
//u1
class QueryUChar_s : public QueryParam_s
{
public:
	QueryUChar_s()
	{
		type = '4';
	}
	void Bind(MYSQL_BIND &bd, unsigned int nLen)
	{
		bd.buffer_type = MYSQL_TYPE_TINY;
		bd.buffer = &val;
		bd.length = &len;
		bd.buffer_length = sizeof(char);
		bd.is_null = &isNull;
		bd.is_unsigned = 1;
	}
	void Reset()
	{
		val = 0;
	}
	const void* GetValueMemory()
	{
		return &val;
	}
	bool SetValue(void* pData, unsigned int nLen)
	{
		if (pData)
		{
			val = *(unsigned char*)pData;
			isNull = 0;
		}
		else
		{
			isNull = 1;
		}
		return true;
	}
private:
	unsigned char val;
};
//i2
class QueryShort_s : public QueryParam_s
{
public:
	QueryShort_s()
	{
		type = '5';
	}
	void Bind(MYSQL_BIND &bd, unsigned int nLen)
	{
		bd.buffer_type = MYSQL_TYPE_SHORT;
		bd.buffer = &val;
		bd.length = &len;
		bd.buffer_length = sizeof(short);
		bd.is_null = &isNull;
		bd.is_unsigned = 0;
	}
	void Reset()
	{
		val = 0;
	}
	const void* GetValueMemory()
	{
		return &val;
	}
	bool SetValue(void* pData, unsigned int nLen)
	{
		if (pData)
		{
			val = *(short*)pData;
			isNull = 0;
		}
		else
		{
			isNull = 1;
		}
		return true;
	}
private:
	short val;
};
//u2
class QueryUShort_s : public QueryParam_s
{
public:
	QueryUShort_s()
	{
		type = '6';
	}
	void Bind(MYSQL_BIND &bd, unsigned int nLen)
	{
		bd.buffer_type = MYSQL_TYPE_SHORT;
		bd.buffer = &val;
		bd.length = &len;
		bd.buffer_length = sizeof(unsigned short);
		bd.is_null = &isNull;
		bd.is_unsigned = 1;
	}
	void Reset()
	{
		val = 0;
	}
	const void* GetValueMemory()
	{
		return &val;
	}
	bool SetValue(void* pData, unsigned int nLen)
	{
		if (pData)
		{
			val = *(unsigned short*)pData;
			isNull = 0;
		}
		else
		{
			isNull = 1;
		}
		return true;
	}
private:
	unsigned short val;
};
//i8
class QueryInt64_s : public QueryParam_s
{
public:
	QueryInt64_s()
	{
		type = '7';
	}
	void Bind(MYSQL_BIND &bd, unsigned int nLen)
	{
		bd.buffer_type = MYSQL_TYPE_LONGLONG;
		bd.buffer = &val;
		bd.length = &len;
		bd.buffer_length = sizeof(long long);
		bd.is_null = &isNull;
		bd.is_unsigned = 0;
	}
	void Reset()
	{
		val = 0;
	}
	const void* GetValueMemory()
	{
		return &val;
	}
	bool SetValue(void* pData, unsigned int nLen)
	{
		if (pData)
		{
			val = *(long long*)pData;
			isNull = 0;
		}
		else
		{
			isNull = 1;
		}
		return true;
	}
private:
	long long	val;
};
//u8
class QueryUInt64_s : public QueryParam_s
{
public:
	QueryUInt64_s()
	{
		type = '8';
	}
	void Bind(MYSQL_BIND &bd, unsigned int nLen)
	{
		bd.buffer_type = MYSQL_TYPE_LONGLONG;
		bd.buffer = &val;
		bd.length = &len;
		bd.buffer_length = sizeof(unsigned long long);
		bd.is_null = &isNull;
		bd.is_unsigned = 1;
	}
	void Reset()
	{
		val = 0;
	}
	const void* GetValueMemory()
	{
		return &val;
	}
	bool SetValue(void* pData, unsigned int nLen)
	{
		if (pData)
		{
			val = *(unsigned long long*)pData;
			isNull = 0;
		}
		else
		{
			isNull = 1;
		}
		return true;
	}
private:
	unsigned long long val;
};
//dt
class QueryDateTime_s : public QueryParam_s
{
public:
	QueryDateTime_s()
	{
		type = '9';
	}
	void Bind(MYSQL_BIND &bd, unsigned int nLen)
	{
		bd.buffer_type = MYSQL_TYPE_DATETIME;
		bd.buffer = &time;
		bd.length = 0;
		bd.buffer_length = sizeof(MYSQL_TIME);
		bd.is_null = &isNull;
		bd.is_unsigned = 0;
	}
	void Reset()
	{
		memset(&time, 0, sizeof(MYSQL_TIME));
	}
	const void* GetValueMemory()
	{
		return &time;
	}
	bool SetValue(void* pData, unsigned int nLen)
	{
		if (nLen != sizeof(MYSQL_TIME))
		{
			return false;
		}
		if (pData)
		{
			::memcpy(&time, pData, nLen);
			isNull = 0;
		}
		else
		{
			isNull = 1;
		}
		return true;
	}
	void SetValue(unsigned int year, unsigned int month, unsigned int day, unsigned int hour, unsigned int minute, unsigned int second)
	{
		time.year = year;
		time.month = month;
		time.day = day;
		time.hour = hour;
		time.minute = minute;
		time.second = second;
		time.neg = false;
		time.time_type = MYSQL_TIMESTAMP_DATETIME;
		isNull = 0;
	}
	void GetValue(ssYMDHMS& ty)
	{
		ty.year.u32p = time.year;
		ty.month.u32p = time.month;
		ty.day.u32p = time.day;
		ty.hour.u32p = time.hour;
		ty.minute.u32p = time.minute;
		ty.second.u32p = time.second;
	}
private:
	MYSQL_TIME time;
};
//s
class QueryString_s : public QueryParam_s
{
public:
	QueryString_s()
	{
		type = 'a';
	}
	void Bind(MYSQL_BIND &bd, unsigned int nLen)
	{
		buf.Init(nLen);
		bd.buffer_type = MYSQL_TYPE_STRING;
		bd.buffer = buf.Buf();
		bd.length = &len;
		bd.buffer_length = nLen;
		bd.is_null = &isNull;
		bd.is_unsigned = 0;
	}
	void Reset()
	{
		buf.Empty();
		len = 0;
	}
	const void* GetValueMemory()
	{
		return buf.Buf();
	}
	bool SetValue(void* pData, unsigned int nLen)
	{
		if (nLen > DB_BUFFER_LEN)
		{
			return false;
		}
		if (pData && nLen)
		{
			len = nLen;
			buf.Write(pData, nLen);
			isNull = 0;
		}
		else
		{
			len = 0;
			isNull = 1;
		}
		return true;
	}
private:
	ssBuffer buf;
};
//b
class QueryBuffer_s : public QueryParam_s
{
public:
	QueryBuffer_s()
	{
		type = 'b';
	}
	void Bind(MYSQL_BIND &bd, unsigned int nLen)
	{
		buf.Init(nLen);
		bd.buffer_type = MYSQL_TYPE_BLOB;
		bd.buffer = buf.Buf();
		bd.length = &len;
		bd.buffer_length = nLen;
		bd.is_null = &isNull;
		bd.is_unsigned = 0;
	}
	void Reset()
	{
		buf.Empty();
		len = 0;
	}
	const void* GetValueMemory()
	{
		return buf.Buf();
	}
	bool SetValue(void* pData, unsigned int nLen)
	{
		if (nLen > DB_BUFFER_LEN)
		{
			return false;
		}
		if (pData && nLen)
		{
			len = nLen;
			buf.Write(pData, nLen);
			isNull = 0;
		}
		else
		{
			len = 0;
			isNull = 1;
		}
		return true;
	}
private:
	ssBuffer buf;
};
//f4
class QueryFloat_s : public QueryParam_s
{
public:
	QueryFloat_s()
	{
		type = 'c';
	}
	void Bind(MYSQL_BIND &bd, unsigned int nLen)
	{
		bd.buffer_type = MYSQL_TYPE_FLOAT;
		bd.buffer = &val;
		bd.length = &len;
		bd.buffer_length = sizeof(float);
		bd.is_null = &isNull;
		bd.is_unsigned = 0;
	}
	void Reset()
	{
		val = 0;
	}
	const void* GetValueMemory()
	{
		return &val;
	}
	bool SetValue(void* pData, unsigned int nLen)
	{
		if (pData)
		{
			val = *(float*)pData;
			isNull = 0;
		}
		else
		{
			isNull = 1;
		}
		return true;
	}
private:
	float	val;
};

struct ssDBResParam
{
	ulint param;
	u32 row;
	u32 insertId;
};

}
#endif
